home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / sendmail-5.65c+IDA-1.4.4.1 / binmail / RCS / binmail.c,v next >
Encoding:
Text File  |  1991-06-25  |  15.1 KB  |  854 lines

  1. head    4.36;
  2. branch    4.36.0;
  3. access;
  4. symbols
  5.     RELEASE:4.36.0.2
  6.     UICSO:4.36.0
  7.     VANILLA:4.36;
  8. locks; strict;
  9. comment    @ * @;
  10.  
  11.  
  12. 4.36
  13. date    90.11.30.14.14.06;    author paul;    state Exp;
  14. branches
  15.     4.36.0.1;
  16. next    ;
  17.  
  18. 4.36.0.1
  19. date    90.11.30.14.22.29;    author paul;    state Exp;
  20. branches;
  21. next    4.36.0.2;
  22.  
  23. 4.36.0.2
  24. date    91.06.25.23.55.57;    author paul;    state Exp;
  25. branches;
  26. next    ;
  27.  
  28.  
  29. desc
  30. @@
  31.  
  32.  
  33.  
  34. 4.36
  35. log
  36. @Sendmail V5.65 distribution
  37. @
  38. text
  39. @#ifndef lint
  40. static char sccsid[] = "@@(#)delivermail.c    4.36 (Berkeley) 4/21/89";
  41. #endif
  42.  
  43. #include <sys/param.h>
  44. #include <sys/stat.h>
  45. #include <sys/file.h>
  46.  
  47. #include <ctype.h>
  48. #include <stdio.h>
  49. #include <pwd.h>
  50. #include <utmp.h>
  51. #include <signal.h>
  52. #include <setjmp.h>
  53. #include <sysexits.h>
  54. #include "pathnames.h"
  55.  
  56.     /* copylet flags */
  57. #define REMOTE        1        /* remote mail, add rmtmsg */
  58. #define ORDINARY    2
  59. #define ZAP        3        /* zap header and trailing empty line */
  60. #define    FORWARD        4
  61.  
  62. #define    LSIZE        256
  63. #define    MAXLET        300        /* maximum number of letters */
  64. #define    MAILMODE    0600        /* mode of created mail */
  65.  
  66. char    line[LSIZE];
  67. char    resp[LSIZE];
  68. struct let {
  69.     long    adr;
  70.     char    change;
  71. } let[MAXLET];
  72. int    nlet    = 0;
  73. char    lfil[50];
  74. long    iop, time();
  75. char    *getenv();
  76. char    *index();
  77. char    lettmp[] = _PATH_TMP;
  78. char    maildir[] = _PATH_MAILDIR;
  79. char    mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
  80. char    dead[] = "dead.letter";
  81. char    forwmsg[] = " forwarded\n";
  82. FILE    *tmpf;
  83. FILE    *malf;
  84. char    my_name[60];
  85. char    *getlogin();
  86. int    error;
  87. int    changed;
  88. int    forward;
  89. char    from[] = "From ";
  90. long    ftell();
  91. int    delex();
  92. char    *ctime();
  93. int    flgf;
  94. int    flgp;
  95. int    delflg = 1;
  96. int    hseqno;
  97. jmp_buf    sjbuf;
  98. int    rmail;
  99.  
  100. main(argc, argv)
  101. char **argv;
  102. {
  103.     register int i;
  104.     char *name;
  105.     struct passwd *pwent;
  106.  
  107.     if (!(name = getlogin()) || !*name || !(pwent = getpwnam(name)) ||
  108.         getuid() != pwent->pw_uid) 
  109.         pwent = getpwuid(getuid());
  110.     strncpy(my_name, pwent ? pwent->pw_name : "???", sizeof(my_name)-1);
  111.     if (setjmp(sjbuf))
  112.         done();
  113.     for (i=SIGHUP; i<=SIGTERM; i++)
  114.         setsig(i, delex);
  115.     i = mkstemp(lettmp);
  116.     tmpf = fdopen(i, "r+");
  117.     if (i < 0 || tmpf == NULL)
  118.         panic("mail: %s: cannot open for writing", lettmp);
  119.     /*
  120.      * This protects against others reading mail from temp file and
  121.      * if we exit, the file will be deleted already.
  122.      */
  123.     unlink(lettmp);
  124.     if (argv[0][0] == 'r')
  125.         rmail++;
  126.     if (argv[0][0] != 'r' &&    /* no favors for rmail*/
  127.        (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd")))
  128.         printmail(argc, argv);
  129.     else
  130.         bulkmail(argc, argv);
  131.     done();
  132. }
  133.  
  134. setsig(i, f)
  135. int i;
  136. int (*f)();
  137. {
  138.     if (signal(i, SIG_IGN) != SIG_IGN)
  139.         signal(i, f);
  140. }
  141.  
  142. any(c, str)
  143.     register int c;
  144.     register char *str;
  145. {
  146.  
  147.     while (*str)
  148.         if (c == *str++)
  149.             return(1);
  150.     return(0);
  151. }
  152.  
  153. printmail(argc, argv)
  154.     char **argv;
  155. {
  156.     int flg, i, j, print;
  157.     char *p, *getarg();
  158.     struct stat statb;
  159.  
  160.     setuid(getuid());
  161.     cat(mailfile, maildir, my_name);
  162. #ifdef notdef
  163.     if (stat(mailfile, &statb) >= 0
  164.         && (statb.st_mode & S_IFMT) == S_IFDIR) {
  165.         strcat(mailfile, "/");
  166.         strcat(mailfile, my_name);
  167.     }
  168. #endif
  169.     for (; argc > 1; argv++, argc--) {
  170.         if (argv[1][0] != '-')
  171.             break;
  172.         switch (argv[1][1]) {
  173.  
  174.         case 'p':
  175.             flgp++;
  176.             /* fall thru... */
  177.         case 'q':
  178.             delflg = 0;
  179.             break;
  180.  
  181.         case 'f':
  182.             if (argc >= 3) {
  183.                 strcpy(mailfile, argv[2]);
  184.                 argv++, argc--;
  185.             }
  186.             break;
  187.  
  188.         case 'b':
  189.             forward = 1;
  190.             break;
  191.  
  192.         default:
  193.             panic("unknown option %c", argv[1][1]);
  194.             /*NOTREACHED*/
  195.         }
  196.     }
  197.     malf = fopen(mailfile, "r");
  198.     if (malf == NULL) {
  199.         printf("No mail.\n");
  200.         return;
  201.     }
  202.     flock(fileno(malf), LOCK_SH);
  203.     copymt(malf, tmpf);
  204.     fclose(malf);            /* implicit unlock */
  205.     fseek(tmpf, 0L, L_SET);
  206.  
  207.     changed = 0;
  208.     print = 1;
  209.     for (i = 0; i < nlet; ) {
  210.         j = forward ? i : nlet - i - 1;
  211.         if (setjmp(sjbuf)) {
  212.             print = 0;
  213.         } else {
  214.             if (print)
  215.                 copylet(j, stdout, ORDINARY);
  216.             print = 1;
  217.         }
  218.         if (flgp) {
  219.             i++;
  220.             continue;
  221.         }
  222.         setjmp(sjbuf);
  223.         fputs("? ", stdout);
  224.         fflush(stdout);
  225.         if (fgets(resp, LSIZE, stdin) == NULL)
  226.             break;
  227.         switch (resp[0]) {
  228.  
  229.         default:
  230.             printf("usage\n");
  231.         case '?':
  232.             print = 0;
  233.             printf("q\tquit\n");
  234.             printf("x\texit without changing mail\n");
  235.             printf("p\tprint\n");
  236.             printf("s[file]\tsave (default mbox)\n");
  237.             printf("w[file]\tsame without header\n");
  238.             printf("-\tprint previous\n");
  239.             printf("d\tdelete\n");
  240.             printf("+\tnext (no delete)\n");
  241.             printf("m user\tmail to user\n");
  242.             printf("! cmd\texecute cmd\n");
  243.             break;
  244.  
  245.         case '+':
  246.         case 'n':
  247.         case '\n':
  248.             i++;
  249.             break;
  250.         case 'x':
  251.             changed = 0;
  252.         case 'q':
  253.             goto donep;
  254.         case 'p':
  255.             break;
  256.         case '^':
  257.         case '-':
  258.             if (--i < 0)
  259.                 i = 0;
  260.             break;
  261.         case 'y':
  262.         case 'w':
  263.         case 's':
  264.             flg = 0;
  265.             if (resp[1] != '\n' && resp[1] != ' ') {
  266.                 printf("illegal\n");
  267.                 flg++;
  268.                 print = 0;
  269.                 continue;
  270.             }
  271.             if (resp[1] == '\n' || resp[1] == '\0') {
  272.                 p = getenv("HOME");
  273.                 if (p != 0)
  274.                     cat(resp+1, p, "/mbox");
  275.                 else
  276.                     cat(resp+1, "", "mbox");
  277.             }
  278.             for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) {
  279.                 malf = fopen(lfil, "a");
  280.                 if (malf == NULL) {
  281.                     printf("mail: %s: cannot append\n",
  282.                         lfil);
  283.                     flg++;
  284.                     continue;
  285.                 }
  286.                 copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY);
  287.                 fclose(malf);
  288.             }
  289.             if (flg)
  290.                 print = 0;
  291.             else {
  292.                 let[j].change = 'd';
  293.                 changed++;
  294.                 i++;
  295.             }
  296.             break;
  297.         case 'm':
  298.             flg = 0;
  299.             if (resp[1] == '\n' || resp[1] == '\0') {
  300.                 i++;
  301.                 continue;
  302.             }
  303.             if (resp[1] != ' ') {
  304.                 printf("invalid command\n");
  305.                 flg++;
  306.                 print = 0;
  307.                 continue;
  308.             }
  309.             for (p = resp+1; (p = getarg(lfil, p)) != NULL; )
  310.                 if (!sendmail(j, lfil, my_name))
  311.                     flg++;
  312.             if (flg)
  313.                 print = 0;
  314.             else {
  315.                 let[j].change = 'd';
  316.                 changed++;
  317.                 i++;
  318.             }
  319.             break;
  320.         case '!':
  321.             system(resp+1);
  322.             printf("!\n");
  323.             print = 0;
  324.             break;
  325.         case 'd':
  326.             let[j].change = 'd';
  327.             changed++;
  328.             i++;
  329.             if (resp[1] == 'q')
  330.                 goto donep;
  331.             break;
  332.         }
  333.     }
  334.    donep:
  335.     if (changed)
  336.         copyback();
  337. }
  338.  
  339. /* copy temp or whatever back to /usr/spool/mail */
  340. copyback()
  341. {
  342.     register int i, c;
  343.     long oldmask;
  344.     int fd, new = 0;
  345.     struct stat stbuf;
  346.  
  347.     oldmask = sigblock(sigmask(SIGINT)|sigmask(SIGHUP)|sigmask(SIGQUIT));
  348.     fd = open(mailfile, O_RDWR | O_CREAT, MAILMODE);
  349.     if (fd >= 0) {
  350.         flock(fd, LOCK_EX);
  351.         malf = fdopen(fd, "r+");
  352.     }
  353.     if (fd < 0 || malf == NULL)
  354.         panic("can't rewrite %s", lfil);
  355.     fstat(fd, &stbuf);
  356.     if (stbuf.st_size != let[nlet].adr) {    /* new mail has arrived */
  357.         fseek(malf, let[nlet].adr, L_SET);
  358.         fseek(tmpf, let[nlet].adr, L_SET);
  359.         while ((c = getc(malf)) != EOF)
  360.             putc(c, tmpf);
  361.         let[++nlet].adr = stbuf.st_size;
  362.         new = 1;
  363.         fseek(malf, 0L, L_SET);
  364.     }
  365.     ftruncate(fd, 0L);
  366.     for (i = 0; i < nlet; i++)
  367.         if (let[i].change != 'd')
  368.             copylet(i, malf, ORDINARY);
  369.     fclose(malf);        /* implict unlock */
  370.     if (new)
  371.         printf("New mail has arrived.\n");
  372.     sigsetmask(oldmask);
  373. }
  374.  
  375. /* copy mail (f1) to temp (f2) */
  376. copymt(f1, f2)
  377.     FILE *f1, *f2;
  378. {
  379.     long nextadr;
  380.  
  381.     nlet = nextadr = 0;
  382.     let[0].adr = 0;
  383.     while (fgets(line, LSIZE, f1) != NULL) {
  384.         if (isfrom(line))
  385.             let[nlet++].adr = nextadr;
  386.         nextadr += strlen(line);
  387.         fputs(line, f2);
  388.     }
  389.     let[nlet].adr = nextadr;    /* last plus 1 */
  390. }
  391.  
  392. copylet(n, f, type)
  393.     FILE *f;
  394. {
  395.     int ch;
  396.     long k;
  397.     char hostname[MAXHOSTNAMELEN];
  398.  
  399.     fseek(tmpf, let[n].adr, L_SET);
  400.     k = let[n+1].adr - let[n].adr;
  401.     while (k-- > 1 && (ch = getc(tmpf)) != '\n')
  402.         if (type != ZAP)
  403.             putc(ch, f);
  404.     switch (type) {
  405.  
  406.     case REMOTE:
  407.         gethostname(hostname, sizeof (hostname));
  408.         fprintf(f, " remote from %s\n", hostname);
  409.         break;
  410.  
  411.     case FORWARD:
  412.         fprintf(f, forwmsg);
  413.         break;
  414.  
  415.     case ORDINARY:
  416.         putc(ch, f);
  417.         break;
  418.  
  419.     case ZAP:
  420.         break;
  421.  
  422.     default:
  423.         panic("Bad letter type %d to copylet.", type);
  424.     }
  425.     while (k-- > 1) {
  426.         ch = getc(tmpf);
  427.         putc(ch, f);
  428.     }
  429.     if (type != ZAP || ch != '\n')
  430.         putc(getc(tmpf), f);
  431. }
  432.  
  433. isfrom(lp)
  434. register char *lp;
  435. {
  436.     register char *p;
  437.  
  438.     for (p = from; *p; )
  439.         if (*lp++ != *p++)
  440.             return(0);
  441.     return(1);
  442. }
  443.  
  444. bulkmail(argc, argv)
  445. char **argv;
  446. {
  447.     char *truename;
  448.     int first;
  449.     register char *cp;
  450.     char *newargv[1000];
  451.     register char **ap;
  452.     register char **vp;
  453.     int dflag;
  454.  
  455.     dflag = 0;
  456.     delflg = 0;
  457.     if (argc < 1) {
  458.         fprintf(stderr, "puke\n");
  459.         return;
  460.     }
  461.     for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++)
  462.         if (ap[0][0] == '-' && ap[0][1] == 'd')
  463.             dflag++;
  464.     if (!dflag) {
  465.         /* give it to sendmail, rah rah! */
  466.         unlink(lettmp);
  467.         ap = newargv+1;
  468.         if (rmail)
  469.             *ap-- = "-s";
  470.         *ap = "-sendmail";
  471.         setuid(getuid());
  472.         execv(_PATH_SENDMAIL, ap);
  473.         perror(_PATH_SENDMAIL);
  474.         exit(EX_UNAVAILABLE);
  475.     }
  476.  
  477.     truename = 0;
  478.     line[0] = '\0';
  479.  
  480.     /*
  481.      * When we fall out of this, argv[1] should be first name,
  482.      * argc should be number of names + 1.
  483.      */
  484.  
  485.     while (argc > 1 && *argv[1] == '-') {
  486.         cp = *++argv;
  487.         argc--;
  488.         switch (cp[1]) {
  489.         case 'r':
  490.             if (argc <= 1)
  491.                 usage();
  492.             truename = argv[1];
  493.             fgets(line, LSIZE, stdin);
  494.             if (strncmp("From", line, 4) == 0)
  495.                 line[0] = '\0';
  496.             argv++;
  497.             argc--;
  498.             break;
  499.  
  500.         case 'h':
  501.             if (argc <= 1)
  502.                 usage();
  503.             hseqno = atoi(argv[1]);
  504.             argv++;
  505.             argc--;
  506.             break;
  507.  
  508.         case 'd':
  509.             break;
  510.         
  511.         default:
  512.             usage();
  513.         }
  514.     }
  515.     if (argc <= 1)
  516.         usage();
  517.     if (truename == 0)
  518.         truename = my_name;
  519.     time(&iop);
  520.     fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop));
  521.     iop = ftell(tmpf);
  522.     flgf = first = 1;
  523.     for (;;) {
  524.         if (first) {
  525.             first = 0;
  526.             if (*line == '\0' && fgets(line, LSIZE, stdin) == NULL)
  527.                 break;
  528.         } else {
  529.             if (fgets(line, LSIZE, stdin) == NULL)
  530.                 break;
  531.         }
  532.         if (*line == '.' && line[1] == '\n' && isatty(fileno(stdin)))
  533.             break;
  534.         if (isfrom(line))
  535.             putc('>', tmpf);
  536.         fputs(line, tmpf);
  537.         flgf = 0;
  538.     }
  539.     putc('\n', tmpf);
  540.     nlet = 1;
  541.     let[0].adr = 0;
  542.     let[1].adr = ftell(tmpf);
  543.     if (flgf)
  544.         return;
  545.     while (--argc > 0)
  546.         if (!sendmail(0, *++argv, truename))
  547.             error++;
  548.     if (error && safefile(dead)) {
  549.         setuid(getuid());
  550.         malf = fopen(dead, "w");
  551.         if (malf == NULL) {
  552.             printf("mail: cannot open %s\n", dead);
  553.             fclose(tmpf);
  554.             return;
  555.         }
  556.         copylet(0, malf, ZAP);
  557.         fclose(malf);
  558.         printf("Mail saved in %s\n", dead);
  559.     }
  560.     fclose(tmpf);
  561. }
  562.  
  563. sendrmt(n, name)
  564. char *name;
  565. {
  566.     FILE *rmf, *popen();
  567.     register char *p;
  568.     char rsys[64], cmd[64];
  569.     register pid;
  570.     int sts;
  571.  
  572. #ifdef notdef
  573.     if (any('^', name)) {
  574.         while (p = index(name, '^'))
  575.             *p = '!';
  576.         if (strncmp(name, "researc", 7)) {
  577.             strcpy(rsys, "research");
  578.             if (*name != '!')
  579.                 --name;
  580.             goto skip;
  581.         }
  582.     }
  583. #endif
  584.     for (p=rsys; *name!='!'; *p++ = *name++)
  585.         if (*name=='\0')
  586.             return(0);    /* local address, no '!' */
  587.     *p = '\0';
  588.     if (name[1]=='\0') {
  589.         printf("null name\n");
  590.         return(0);
  591.     }
  592. skip:
  593.     if ((pid = fork()) == -1) {
  594.         fprintf(stderr, "mail: can't create proc for remote\n");
  595.         return(0);
  596.     }
  597.     if (pid) {
  598.         while (wait(&sts) != pid) {
  599.             if (wait(&sts)==-1)
  600.                 return(0);
  601.         }
  602.         return(!sts);
  603.     }
  604.     setuid(getuid());
  605.     if (any('!', name+1))
  606.         (void)sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1);
  607.     else
  608.         (void)sprintf(cmd, "uux - %s!rmail %s", rsys, name+1);
  609.     if ((rmf=popen(cmd, "w")) == NULL)
  610.         exit(1);
  611.     copylet(n, rmf, REMOTE);
  612.     exit(pclose(rmf) != 0);
  613. }
  614.  
  615. usage()
  616. {
  617.  
  618.     fprintf(stderr, "Usage: mail [ -f ] people . . .\n");
  619.     error = EX_USAGE;
  620.     done();
  621. }
  622.  
  623. #include <sys/socket.h>
  624. #include <netinet/in.h>
  625. #include <netdb.h>
  626.  
  627. notifybiff(msg)
  628.     char *msg;
  629. {
  630.     static struct sockaddr_in addr;
  631.     static int f = -1;
  632.  
  633.     if (addr.sin_family == 0) {
  634.         struct hostent *hp = gethostbyname("localhost");
  635.         struct servent *sp = getservbyname("biff", "udp");
  636.  
  637.         if (hp && sp) {
  638.             addr.sin_family = hp->h_addrtype;
  639.             bcopy(hp->h_addr, &addr.sin_addr, hp->h_length);
  640.             addr.sin_port = sp->s_port;
  641.         }
  642.     }
  643.     if (addr.sin_family) {
  644.         if (f < 0)
  645.             f = socket(AF_INET, SOCK_DGRAM, 0);
  646.         if (f >= 0)
  647.             sendto(f, msg, strlen(msg)+1, 0, &addr, sizeof (addr));
  648.     }
  649. }
  650.  
  651. sendmail(n, name, fromaddr)
  652.     int n;
  653.     char *name, *fromaddr;
  654. {
  655.     char file[256];
  656.     int mask, fd;
  657.     struct passwd *pw;
  658. #ifdef notdef
  659.     struct stat statb;
  660. #endif
  661.     char buf[128];
  662.  
  663.     if (*name=='!')
  664.         name++;
  665.     if (any('!', name))
  666.         return (sendrmt(n, name));
  667.     if ((pw = getpwnam(name)) == NULL) {
  668.         printf("mail: can't send to %s\n", name);
  669.         return(0);
  670.     }
  671.     cat(file, maildir, name);
  672. #ifdef notdef
  673.     if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) {
  674.         strcat(file, "/");
  675.         strcat(file, name);
  676.     }
  677. #endif
  678.     if (!safefile(file))
  679.         return(0);
  680.     fd = open(file, O_WRONLY | O_CREAT, MAILMODE);
  681.     if (fd >= 0) {
  682.         flock(fd, LOCK_EX);
  683.         malf = fdopen(fd, "a");
  684.     }
  685.     if (fd < 0 || malf == NULL) {
  686.         close(fd);
  687.         printf("mail: %s: cannot append\n", file);
  688.         return(0);
  689.     }
  690.     fchown(fd, pw->pw_uid, pw->pw_gid);
  691.     (void)sprintf(buf, "%s@@%ld\n", name, ftell(malf));
  692.     copylet(n, malf, ORDINARY);
  693.     fclose(malf);
  694.     notifybiff(buf);
  695.     return(1);
  696. }
  697.  
  698. delex(i)
  699. {
  700.     if (i != SIGINT) {
  701.         setsig(i, SIG_DFL);
  702.         sigsetmask(sigblock(0L) &~ sigmask(i));
  703.     }
  704.     putc('\n', stderr);
  705.     if (delflg)
  706.         longjmp(sjbuf, 1);
  707.     if (error == 0)
  708.         error = i;
  709.     done();
  710. }
  711.  
  712. done()
  713. {
  714.  
  715.     unlink(lettmp);
  716.     exit(error);
  717. }
  718.  
  719. cat(to, from1, from2)
  720.     char *to, *from1, *from2;
  721. {
  722.     register char *cp, *dp;
  723.  
  724.     cp = to;
  725.     for (dp = from1; *cp = *dp++; cp++)
  726.         ;
  727.     for (dp = from2; *cp++ = *dp++; )
  728.         ;
  729. }
  730.  
  731. /* copy p... into s, update p */
  732. char *
  733. getarg(s, p)
  734.     register char *s, *p;
  735. {
  736.     while (*p == ' ' || *p == '\t')
  737.         p++;
  738.     if (*p == '\n' || *p == '\0')
  739.         return(NULL);
  740.     while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
  741.         *s++ = *p++;
  742.     *s = '\0';
  743.     return(p);
  744. }
  745.  
  746. safefile(f)
  747.     char *f;
  748. {
  749.     struct stat statb;
  750.  
  751.     if (lstat(f, &statb) < 0)
  752.         return (1);
  753.     if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) {
  754.         fprintf(stderr,
  755.             "mail: %s has more than one link or is a symbolic link\n",
  756.             f);
  757.         return (0);
  758.     }
  759.     return (1);
  760. }
  761.  
  762. panic(msg, a1, a2, a3)
  763.     char *msg;
  764. {
  765.  
  766.     fprintf(stderr, "mail: ");
  767.     fprintf(stderr, msg, a1, a2, a3);
  768.     fprintf(stderr, "\n");
  769.     done();
  770. }
  771. @
  772.  
  773.  
  774. 4.36.0.1
  775. log
  776. @Date:    Fri, 23 Nov 90 14:44:41 +1300
  777. To:      "Paul Pomes, UofIllinois-CSO" <paul@@uxc.cso.uiuc.edu>
  778. From:    Andy.Linton@@comp.vuw.ac.nz
  779. Subject: locking in /bin/mail (with the details (:-))
  780. X-Mailer: XMH (using mh 6.7) 
  781.  
  782. We use the LCK_BEL locking in 'mh' as we have the spool directory mounted via
  783. NFS. The flock (real or emulated) is not good enough and results in races
  784. which unfortunately end up in "dead heats" at times.
  785. @
  786. text
  787. @a120 4
  788. #if defined(MH_LCK_BEL)
  789.     int lk_fd;
  790.     extern int lkopen(), lkclose();
  791. #endif /* MH_LCK_BEL */
  792. a158 7
  793. #if defined(LOCKF_FLOCK)
  794.     /*
  795.          * We can't get a lock on a file that
  796.          * isn't opened for writing - sigh!
  797.          */
  798.         malf = fopen(mailfile, "r+");
  799. #else
  800. a159 1
  801. #endif /* LOCKF_FLOCK */
  802. a163 3
  803. #if defined(MH_LCK_BEL)
  804.     lk_fd = lkopen(mailfile, O_RDONLY);
  805. #endif /* MH_LCK_BEL */
  806. a166 3
  807. #if defined(MH_LCK_BEL)
  808.     (void) lkclose(lk_fd, mailfile);
  809. #endif /* MH_LCK_BEL */
  810. a307 4
  811. #if defined(MH_LCK_BEL)
  812.     int lk_fd;
  813.     extern int lkopen(), lkclose();
  814. #endif /* MH_LCK_BEL */
  815. d312 2
  816. a313 5
  817. #if defined(MH_LCK_BEL)
  818.         lk_fd = lkopen(mailfile, O_RDWR);
  819. #endif /* MH_LCK_BEL */
  820.         flock(fd, LOCK_EX);
  821.         malf = fdopen(fd, "r+");
  822. a331 3
  823. #if defined(MH_LCK_BEL)
  824.     (void) lkclose(lk_fd, mailfile);
  825. #endif /* MH_LCK_BEL */
  826. a623 4
  827. #if defined(MH_LCK_BEL)
  828.     int lk_fd;
  829.     extern int lkopen(), lkclose();
  830. #endif /* MH_LCK_BEL */
  831. d644 2
  832. a645 5
  833. #if defined(MH_LCK_BEL)
  834.         lk_fd = lkopen(mailfile, O_RDWR);
  835. #endif /* MH_LCK_BEL */
  836.         flock(fd, LOCK_EX);
  837.         malf = fdopen(fd, "a");
  838. a655 4
  839. #if defined(MH_LCK_BEL)
  840.     (void) lkclose(lk_fd, mailfile);
  841. #endif /* MH_LCK_BEL */
  842.  
  843. @
  844.  
  845.  
  846. 4.36.0.2
  847. log
  848. @Added rcsid[] string.
  849. @
  850. text
  851. @a2 1
  852. static char  rcsid[] = "@@(#)$Id$";
  853. @
  854.